package com.infore.dataAudit.service.audit.impl;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.activiti.engine.HistoryService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.infore.dataAudit.dto.AuditDataInfo;
import com.infore.dataAudit.dto.Project;
import com.infore.dataAudit.dto.StationInfo;
import com.infore.dataAudit.entity.TDataAudit;
import com.infore.dataAudit.entity.TDataAuditDetail;
import com.infore.dataAudit.entity.TDataAuditRecord;
import com.infore.dataAudit.entity.TDataAuditSignRecord;
import com.infore.dataAudit.entity.TEvidenceFile;
import com.infore.dataAudit.enums.AirAuditUsers;
import com.infore.dataAudit.enums.AuditStatus;
import com.infore.dataAudit.enums.ResultStatus;
import com.infore.dataAudit.exception.ActivitiException;
import com.infore.dataAudit.remote.IBaseDataService;
import com.infore.dataAudit.repository.ITDataAuditDetailRepository;
import com.infore.dataAudit.repository.ITDataAuditRecordRepository;
import com.infore.dataAudit.repository.ITDataAuditRepository;
import com.infore.dataAudit.repository.ITDataAuditSignRecordRepository;
import com.infore.dataAudit.repository.ITEvidenceRepository;
import com.infore.dataAudit.service.EntityMapService;
import com.infore.dataAudit.service.TasksService;
import com.infore.dataAudit.service.audit.IDataAuditService;
import com.infore.dataAudit.util.AuditDataCovertUtil;
import com.infore.dataAudit.util.Constants;
import com.infore.dataAudit.util.DateFormatUtil;
import com.infore.dataAudit.util.ObjectMapperUtil;
import com.infore.dataAudit.util.PageObject;
import com.infore.dataAudit.util.PageUtil;
import com.infore.dataAudit.util.ResultEntity;
import com.infore.dataAudit.util.UUIDGenerator;
import com.infore.dataAudit.vo.AuditRecordQuery;
import com.infore.dataAudit.vo.CustomerDataAuditVO;
import com.infore.dataAudit.vo.DataAuditBO;
import com.infore.dataAudit.vo.DataAuditRecordVO;
import com.infore.dataAudit.vo.DataAuditVO;
import com.infore.dataAudit.vo.QualityParamOutSelectBo;
import com.infore.dataAudit.vo.StatisAuditDateVO;


@Service("dataAuditService")
public class DataAuditServiceImpl implements IDataAuditService {
    
    @Autowired
    private ITDataAuditRepository dataAuditRepository;
    @Autowired
    private ITDataAuditRecordRepository dataAuditRecordRepository;
    @Autowired
    private ITDataAuditSignRecordRepository dataAuditSignRecordRepository;
    @Autowired
    private ITDataAuditDetailRepository dataAuditDetailRepository;
    @Autowired
    private ITEvidenceRepository evidenceRepository;
    
    @Autowired  
    private TasksService tasksService;  
    
    @Resource
    private HistoryService historyService;
    @Autowired
    private IBaseDataService baseDataService;
    @Autowired
    private ObjectMapperUtil objectMapperUtil;
    @Autowired
    private EntityMapService entityMapService;
    
    @Override
    public ResultEntity queryAuditDataByTimeAndMns(QualityParamOutSelectBo bo) {
        String startTime = bo.getStartTime() + " 00:00:00";
        String endTime = bo.getEndTime() + " 23:59:00";
        List<String> mnList = bo.getStationCodes();
        boolean page = bo.getPageNumber() != null && bo.getPageSize() != null;
        if(startTime == null || endTime == null) {
            return new ResultEntity(ResultStatus.ERROR,"时间不能为空");
        }
        if(mnList == null || mnList.size() == 0) {
            return new ResultEntity(ResultStatus.ERROR,"监测站mn不能为空");
        }
        List<AuditDataInfo> infoList = new ArrayList<>();
        //有效数据监测站因子 集合map
        Map<String, Integer> viNumMap = new HashMap<>();
        String stationMN = null;
        String projId = null;
        String projName = null;
        int num = 0;
        //有效数据量
        List<Map<String,Object>> validateMap = dataAuditRepository.statisAuditDataValidate(mnList, startTime, endTime);
        for (Map<String, Object> map : validateMap) {
            stationMN = map.get("STATION_MN") == null?null:map.get("STATION_MN").toString();
            projId = map.get("PROJ_ID") == null?null:map.get("PROJ_ID").toString();
            projName = map.get("PROJ_NAME") == null?null:map.get("PROJ_NAME").toString();
            num = map.get("CNUM") == null?0:Integer.valueOf(map.get("CNUM").toString());
            if(projName!= null && stationMN != null && projId != null) {
                String key = stationMN +"-"+projId;
                viNumMap.put(key, num);
            }
        }
        //监测站点信息
        Map<String,StationInfo> stationMap = this.queryStationInfos(mnList);
        AuditDataInfo info = null;
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位  
        numberFormat.setMaximumFractionDigits(2); 
        List<Map<String,Object>> countMap = dataAuditRepository.statisAuditDataCount(mnList, startTime, endTime);
        int yUploadNum = 0; //站点监测项目的应上传数 未设置 默认0
        for (Map<String, Object> map : countMap) {
            stationMN = map.get("STATION_MN") == null?null:map.get("STATION_MN").toString();
            projId = map.get("PROJ_ID") == null?null:map.get("PROJ_ID").toString();
            projName = map.get("PROJ_NAME") == null?null:map.get("PROJ_NAME").toString();
            num = map.get("CNUM") == null?0:Integer.valueOf(map.get("CNUM").toString());//实际上传数
            if(projName!= null && stationMN != null && projId != null) {
                String key = stationMN +"-"+projId;
                StationInfo stationInfo = stationMap.get(stationMN);
                info = new AuditDataInfo();
                infoList.add(info);
                info.setProjId(projId);
                info.setProjName(projName);
                info.setStationMn(stationMN);
                info.setsUploadNum(num);
                int validNum = viNumMap.get(key) == null ? 0 : viNumMap.get(key);
                String result = numberFormat.format((float) validNum / (float) num * 100);
                info.setValidNum(validNum);
                info.setValidRate(result+"%");
                if(yUploadNum == 0) {
                    info.setUploadRate("100%");
                }
                if(stationInfo != null) {
                    info.setStationName(stationInfo.getStationName());
                    info.setStationProvin(stationInfo.getStationProvin());
                    info.setRiverBasin(stationInfo.getRiverBasin());
                }
                
            }
        }
        if(page) {
        	PageObject pageObject = new PageObject();
        	pageObject.setPageNumber(bo.getPageNumber());
        	pageObject.setPageSize(bo.getPageSize());
            return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setPage(PageUtil.inventedObjectPage(infoList, pageObject));
        }
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(infoList);
            
            
    }
    
    private void setAuditStatus(AuditDataInfo info, List<TDataAuditDetail> auditDetailsList, String threeAuditClass) {
        for (TDataAuditDetail tDataAuditDetail : auditDetailsList) {
            if(threeAuditClass.equals(tDataAuditDetail.getTaskName())) {
                info.setAuditStatus(tDataAuditDetail.getAuditStatus());
                break;
            }
        }
        
    }

    @Override
    public ResultEntity queryAuditDataByTimeAndMn(String startTime, String endTime, String mn) {
        if(startTime == null || endTime == null) {
            return new ResultEntity(ResultStatus.ERROR,"时间不能为空");
        }
        if(mn == null) {
            return new ResultEntity(ResultStatus.ERROR,"监测站mn不能为空");
        }
        Map<String, Object> re = wrapAuditData(startTime, endTime, mn);
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(re);
    }

    private Map<String, Object> wrapAuditData(String startTime, String endTime, String mn) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat hourSdf = new SimpleDateFormat("yyyy-MM-dd HH");
        long endMiss = 0L;
        long startMiss = 0L;
        try {
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            //加上 23：59：59
            endMiss = endDate.getTime() + 23*60*60*1000 + 59*60*1000 + 59*1000;
            startMiss = startDate.getTime();
        } catch (ParseException e) {
            throw new ActivitiException("数据格式错误!");
        }
        List<Project> projectInfos = this.projectInfoAllAudit(mn);
        List<TDataAudit> list = dataAuditRepository.findByCreateTimeBetweenAndStationMnOrderByCreateTimeAsc
                    (new Timestamp(startMiss), new Timestamp(endMiss), mn);
        List<Map<String, DataAuditBO>> result = AuditDataCovertUtil.initDataAuditBOs(startMiss, endMiss, projectInfos);
        String assignee = "assignee";
        List<Task> tasks = null;
        //解析梳理时间使符合页面数据
        String oldFlowId = "";
        for (TDataAudit tDataAudit : list) {
            if(!tDataAudit.getFlowInstanceId().equals(oldFlowId)) {
                tasks = tasksService.queryTask(tDataAudit.getFlowInstanceId(), assignee,"");
                oldFlowId = tDataAudit.getFlowInstanceId();
            }
            AuditDataCovertUtil.convertDataAuditBOs(result, tDataAudit, tasks);
        }
        
        Map<String,Object> re = new HashMap<>();
        re.put("head", AuditDataCovertUtil.getDataAuditHead(projectInfos));
        re.put("body", result);
        return re;
    }
    
    @Override
    public ResultEntity queryEchartsAuditDataByTimeAndMn(String startTime, String endTime, String mn) {
        if(startTime == null || endTime == null) {
            return new ResultEntity(ResultStatus.ERROR,"时间不能为空");
        }
        if(mn == null) {
            return new ResultEntity(ResultStatus.ERROR,"监测站mn不能为空");
        }
        List<Project> projectInfos = this.projectInfoAllAudit(mn);
        List<Map<String, Object>> series = new ArrayList<>();
        Map<String, Object> serie = null;
        List<String> legend = new ArrayList<>();
        for (Project project : projectInfos) {
            serie = new HashMap<>();
            serie.put("name", project.getProjectName());
            legend.add(project.getProjectName());
            serie.put("type", "line");
            serie.put("id",  project.getProjectCode());
            serie.put("data", new ArrayList<Map<String, String>>());
            series.add(serie);
        }
        Map<String, Object> re = wrapAuditData(startTime, endTime, mn);
        List<Map<String, DataAuditBO>> list = (List<Map<String, DataAuditBO>>) re.get("body");
        List<String> xdata = new ArrayList<>();
        DataAuditBO bo = null;
        Map<String, String> data = null;
        List<Map<String, String>> datas = null;
        for (Map<String, DataAuditBO> map : list) {
            xdata.add(map.get("time").getValue());
            int i = 0;
            for (Project project : projectInfos) {
                bo = map.get(project.getProjectCode());
                data = new HashMap<>();
                datas = (List<Map<String, String>>)series.get(i).get("data");
                datas.add(data);
                if(bo != null) {
                    data.put("name", bo.getFlowId());
                    data.put("value", bo.getValue());
                }
                i ++;
            }
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("xdata", xdata);
        result.put("legend", legend);
        result.put("series", series);
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setInfo(result);
    }
    
    
    
    @Override
    public List<Project> projectInfoAllAudit(String mn) {
        
        ResultEntity re = baseDataService.projectInfoByMn(Arrays.asList(mn));
        List<Project> ProjectList = objectMapperUtil.convertList(re, Project.class);
        if(mn != null) {
            List<String> mnList = new ArrayList<>();
            mnList.add(mn);
            Map<String,StationInfo> stationMap = this.queryStationInfos(mnList);
            StationInfo station = stationMap.get(mn);
            Iterator<Project> it = ProjectList.iterator();
            while (it.hasNext()) {
                Project project =  it.next();
                String code = project.getProjectCode();
                //水
                if(station != null && "001".equals(station.getStationType())) {
                    if(project.getProjectCode().equals("w01018")) {
                        it.remove();
                    }
                }
                if(station != null && "002".equals(station.getStationType())) {
                    if(code.equals("w01010") || code.equals("w01009") ||code.equals("w01003")
                            || code.equals("w01014")|| code.equals("w01019")) {
                        it.remove();
                    }
                }
                
            }
        }
        return ProjectList;
    }

    @Override
    public ResultEntity saveTDataAudit(List<TDataAudit> list) {
        return null;
    }
    
    @Override
    public ResultEntity queryDataAuditDetailStatisPage(AuditRecordQuery query, String status) {
        String startTime = query.getStartTime();
        String endTime = query.getEndTime();
        List<String> stationMn = query.getStationMnList();
        //Sort sort = new Sort(Sort.Direction.DESC, "dataAudit.stationMn","dataAudit.createTime");
        Pageable pageable =  query.isPage() ? PageRequest.of(query.getPageObject().getPageNumber() -1 ,
                query.getPageObject().getPageSize()):
                null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Page<TDataAuditDetail> page = null;
        List<TDataAuditDetail> list = null;
        try {
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            Specification<TDataAuditDetail> specification = new Specification<TDataAuditDetail>() {
                @Override
                public Predicate toPredicate(Root<TDataAuditDetail> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    List<Predicate> predicates = new ArrayList<>();
                    Join join = root.join("dataAudit");
                    predicates.add(cb.between(join.get("createTime"), startDate, endDate));
                    predicates.add(cb.equal(root.get("auditStatus"), status));
                    if(stationMn.size() > 0) {
                        predicates.add(join.get("stationMn").in(stationMn));
                    }
                    Predicate[] p = new Predicate[predicates.size()];
                    query.where(cb.and(predicates.toArray(p)));
                    query.orderBy(cb.asc(join.get("stationMn")), cb.asc(join.get("createTime")));
                    return query.getRestriction();
                }
            };
            if(pageable != null) {
                page = dataAuditDetailRepository.findAll(specification, pageable);
                list = page.getContent();
            }else {
                list = dataAuditDetailRepository.findAll(specification);
            }
           
        } catch (ParseException e) {
            return new ResultEntity(ResultStatus.ERROR, "时间格式错误，格式：yyyy-MM-dd");
        }
        //查询
        Set<String> mnSet = new HashSet<>();
        for (TDataAuditDetail detail : list) {
            String smn = detail.getDataAudit().getStationMn();
            mnSet.add(smn);
        }
        List<String> stationMnList = new ArrayList<>();
        stationMnList.addAll(mnSet);
        Map<String,StationInfo> stationMap = this.queryStationInfos(stationMnList);
        this.setStationInfoToDeatilRecord(list, stationMap);
        return page == null ? new ResultEntity(ResultStatus.ERROR, Constants.QUERY_SUCCESS).setDataList(list)
                :ResultEntity.page(page);
    }
    


    private void setStationInfoToDeatilRecord(List<TDataAuditDetail> list, Map<String, StationInfo> stationMap) {
        StationInfo station = null;
        for (TDataAuditDetail detail : list) {
            String mn = detail.getDataAudit().getStationMn();
            station = stationMap.get(mn);
            if(station == null)
                continue;
            detail.getDataAudit().setStationCity(station.getStationCity());
            detail.getDataAudit().setStationCompany(station.getStationCompany());
            detail.getDataAudit().setStationName(station.getStationName());
            detail.getDataAudit().setStationProvin(station.getStationProvin());
        }
    }

    @Override
    public ResultEntity queryDataAuditRecordPage(AuditRecordQuery query) {
        String startTime = query.getStartTime();
        String endTime = query.getEndTime();
        String auditOperation = query.getAuditOperation();
        String mn = query.getMn();
        List<String> mnList = query.getStationMnList();
        if(mnList == null || mnList.size() == 0) {
            return new ResultEntity(ResultStatus.ERROR, "监测站mnlits未存在"); 
        }
        
      //  Sort sort = new Sort(Sort.Direction.DESC, "stationName","auditDate");
        Pageable pageable =  query.isPage() ? PageRequest.of(query.getPageObject().getPageNumber() -1 ,
                query.getPageObject().getPageSize()):
                null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Page<TDataAuditRecord> page = null;
        List<TDataAuditRecord> list = null;
        try {
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            Specification<TDataAuditRecord> specification = new Specification<TDataAuditRecord>() {
                @Override
                public Predicate toPredicate(Root<TDataAuditRecord> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Predicate p1 = cb.between(root.get("stationDate"), startDate, endDate);
                    Predicate p2 = cb.or(cb.like(root.get("stationName"), "%" + mn + "%"),
                            cb.like(root.get("stationMn"), "%" + mn + "%"));
                    Predicate p3 = cb.and(root.get("stationMn").in(mnList));
                    
                    if (auditOperation != null && !auditOperation.trim().equals("")) {
                        query.where(cb.and(p1, p2, p3, cb.like(root.get("auditOperation"), "%" + auditOperation + "%")));
                    } else {
                        query.where(cb.and(p1, p2,p3));
                    }
                    query.orderBy(cb.desc(root.get("stationName")),cb.desc(root.get("stationDate")));
                    return query.getRestriction();
                }
            };
            if(pageable != null) {
                page = dataAuditRecordRepository.findAll(specification, pageable);
                list = page.getContent();
            }else {
                list = dataAuditRecordRepository.findAll(specification);
            }
           
        } catch (ParseException e) {
            return new ResultEntity(ResultStatus.ERROR, "时间格式错误，格式：yyyy-MM-dd");
        }
        //查询
        Set<String> mnSet = new HashSet<>();
        for (TDataAuditRecord record : list) {
            String smn = record.getStationMn();
            mnSet.add(smn);
        }
        List<String> stationMnList = new ArrayList<>();
        stationMnList.addAll(mnSet);
        Map<String,StationInfo> stationMap = this.queryStationInfos(stationMnList);
        this.setStationInfoToRecord(list, stationMap);
        return page == null ? new ResultEntity(ResultStatus.ERROR, "成功").setDataList(list)
                :ResultEntity.page(page);
    }

    private void setStationInfoToRecord(List<TDataAuditRecord> list, Map<String, StationInfo> stationMap) {
        StationInfo station = null;
        for (TDataAuditRecord tDataAuditRecord : list) {
            String mn = tDataAuditRecord.getStationMn();
            station = stationMap.get(mn);
            if(station == null)
                continue;
            tDataAuditRecord.setStationCity(station.getStationCity());
            tDataAuditRecord.setStationCompany(station.getStationCompany());
            tDataAuditRecord.setStationName(station.getStationName());
            tDataAuditRecord.setStationProvin(station.getStationProvin());
        }
        
    }

    private Map<String, StationInfo> queryStationInfos(List<String> stationMnList) {
        ResultEntity stationInfoRe = baseDataService.stationInfoAudit(stationMnList);
        List<StationInfo> stationList = objectMapperUtil.convertList(stationInfoRe, StationInfo.class);
        Map<String, StationInfo> map = new HashMap<>();
        for (StationInfo stationInfo : stationList) {
            map.put(stationInfo.getStationMn(), stationInfo);
        }
        return map;
    }

    @Override
    public List<TDataAudit> autoCompleteOneAudit(Map<String, Object> params) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String stationTime = (String) params.get("stationTime");
        String stationMn = (String) params.get("stationMn");
        String flowId = (String) params.get("flowId");
        String assignee = (String) params.get("assignee");
        Date date = null;
        try {
            date = sdf.parse(stationTime);
        } catch (ParseException e) {
            return new ArrayList<>();
        }
        
        List<TDataAudit> list = dataAuditRepository.findByFlowInstanceId(flowId);
      //保存数据的审核详情 一级 二级 三级审核
        this.saveTDataAuditDetails(list, null,Constants.ONE_AUDIT_CLASS);
        TDataAuditRecord record = new TDataAuditRecord();
        record.setAuditDate(new Date());
        record.setAuditOperation(Constants.ONE_AUDIT_OPERATION);
        record.setAuditReason(Constants.REASON_AUTO_AUDIT_OK);
        record.setAuditUser(Constants.ASSIGNEE_AUTO_AUDIT);
        record.setFlowInstanceId(flowId);
        record.setStationDate(date);
        record.setStationMn(stationMn);
        dataAuditRepository.flush();
        dataAuditRecordRepository.save(record);
        //完成一级审核任务
        List<Task> tasks = tasksService.queryTask(flowId, assignee,"");
        for (Task task : tasks) {
            if(task.getName().equals(Constants.ONE_AUDIT_CLASS)) {
                //tasksService.finishTask(task, null, null, null);
                System.out.println("一级审核定时启动 ----- ");
            }
        }
        return list;
    }

    @Override
    public List<TDataAudit> autoCompleteTwoAudit(Map<String, Object> params) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String stationTime = (String) params.get("stationTime");
        String stationMn = (String) params.get("stationMn");
        String flowId = (String) params.get("flowId");
        String assignee = (String) params.get("assignee");
        Date date = null;
        try {
            date = sdf.parse(stationTime);
        } catch (ParseException e) {
            return new ArrayList<>();
        }
        
        List<TDataAudit> list = dataAuditRepository.findByFlowInstanceId(flowId);
        //保存数据的审核详情 一级 二级 三级审核
        this.saveTDataAuditDetails(list, Constants.ONE_AUDIT_CLASS,Constants.TWO_AUDIT_CLASS);
        
        TDataAuditRecord record = new TDataAuditRecord();
        record.setAuditDate(new Date());
        record.setAuditOperation(Constants.TWO_AUDIT_OPERATION);
        record.setAuditReason(Constants.REASON_AUTO_AUDIT_OK);
        record.setAuditUser(Constants.ASSIGNEE_AUTO_AUDIT);
        record.setFlowInstanceId(flowId);
        record.setStationDate(date);
        record.setStationMn(stationMn);
        dataAuditRepository.flush();
        dataAuditRecordRepository.save(record);
      //完成二级级审核任务
        List<Task> tasks = tasksService.queryTask(flowId, assignee, "");
        for (Task task : tasks) {
            if(task.getName().equals(Constants.TWO_AUDIT_CLASS)) {
                //tasksService.finishTask(task, null, null, null);
                System.out.println("二级审核定时启动 ----- ");
            }
        }
        return list;
    }
    
    private void saveTDataAuditDetails(List<TDataAudit> dataList, String taskName, String comment,
            String assignee) {
        List<TDataAuditDetail> details = new ArrayList<>();
        
        TDataAuditDetail detail = null;
        for (TDataAudit tDataAudit : dataList) {
            detail = new TDataAuditDetail();
            detail.setTaskName(taskName);
            detail.setDataAudit(tDataAudit);
            detail.setAuditUser(assignee);
            //设置数据审核状态
            detail = this.setAuditStatusDesc(detail, tDataAudit, taskName);
            detail.setAuditConDesc(comment);
            details.add(detail);
            //最终三级审核
            if(taskName.equals(Constants.THREE_AUDIT_CLASS)) {
                tDataAudit.setAuditStatus(detail.getAuditStatus());
                tDataAudit.setAuditStatusDesc(detail.getAuditDesc());
            }
        }
        if(taskName.equals(Constants.THREE_AUDIT_CLASS)) {
            dataAuditRepository.flush();
        }
        dataAuditDetailRepository.saveAll(details);
    }
    
    private TDataAuditDetail setAuditStatusDesc(TDataAuditDetail detail, TDataAudit tDataAudit, String taskName) {
        List<TDataAuditDetail> detailsList = tDataAudit.getAuditDetailsList();
        if(detailsList == null || detailsList.size() == 0) {
            detail.setAuditStatus(tDataAudit.getXtAudit());
            detail.setAuditDesc(tDataAudit.getXtAuditDesc());
        }
        TDataAuditDetail one = null;
        TDataAuditDetail two = null;
        boolean over = false;
        for (TDataAuditDetail tDataAuditDetail : detailsList) {
            if(tDataAuditDetail.getTaskName().equals(taskName)) {
                detail = tDataAuditDetail;
                over = true;
                break;
            }
            if(tDataAuditDetail.getTaskName().equals(Constants.ONE_AUDIT_CLASS)) {
                one = tDataAuditDetail;
            }
            if(tDataAuditDetail.getTaskName().equals(Constants.TWO_AUDIT_CLASS)) {
                two = tDataAuditDetail;
            }
        }
        if(!over) {
            if(one != null) {
                detail.setAuditStatus(one.getAuditStatus());
                detail.setAuditDesc(one.getAuditDesc());
            }
            if(two != null) {
                detail.setAuditStatus(two.getAuditStatus());
                detail.setAuditDesc(two.getAuditDesc());
            }
        }
        return detail;
    }

    /**
     * 存储审核详情 数据的一级 二级 三级审核详情
     * 
     * @author 蔡永顺
     * @return void
     * @param list
     * @param taskName 
     * @param dTaskName 
     * @date 2019年5月9日上午10:25:18
     */
    private void saveTDataAuditDetails(List<TDataAudit> list, String taskName, String dTaskName) {
        List<TDataAuditDetail> details = new ArrayList<>();
        TDataAuditDetail detail = null;
        for (TDataAudit tDataAudit : list) {
            detail = new TDataAuditDetail();
            detail.setAuditConDesc(Constants.REASON_AUTO_AUDIT_OK);
            detail.setAuditUser(Constants.ASSIGNEE_AUTO_AUDIT);
            detail.setTaskName(dTaskName);
            detail.setDataAudit(tDataAudit);
            detail.setAuditStatus(tDataAudit.getXtAudit());
            detail.setAuditDesc(tDataAudit.getXtAuditDesc());
            if(taskName != null) {
                List<TDataAuditDetail> detailsA = tDataAudit.getAuditDetailsList();
                for (TDataAuditDetail tDataAuditDetail : detailsA) {
                    if(taskName.equals(tDataAuditDetail.getTaskName())) {
                        detail = tDataAuditDetail;
                        detail.setAuditStatus(tDataAuditDetail.getAuditStatus());
                        detail.setAuditDesc(tDataAuditDetail.getAuditDesc());
                    }
                }
            }
            details.add(detail);
        }
        dataAuditDetailRepository.saveAll(details);
    }

    @Override
    public ResultEntity auditCustomerTask(CustomerDataAuditVO vo, String appCode) {
        if(vo == null) {
            return new ResultEntity(ResultStatus.ERROR,"审核数据为空");
        }
        List<Map<String, DataAuditBO>> list = vo.getList();
        String comment = vo.getComment();
        String assignee = vo.getUserId();
        String userId = vo.getUserId();
        System.out.println("登陆用户id=== "+userId);
        TDataAudit data = null;
        Task task = null;
        List<Task> tasks = null;
        String taskName = "";
        Map<String,String> flowMap = new HashMap<>();
        List<TDataAudit> dataList = null;
        for (Map<String, DataAuditBO> map : list) {
            for (DataAuditBO bo: map.values()) {
                String id = bo.getId();
                String flowId = bo.getFlowId();
                if(id != null && flowId != null && flowMap.get(flowId) == null) {
                    data = dataAuditRepository.findById(id).get();
                    flowMap.put(flowId, flowId);
                    tasks = tasksService.queryTask(flowId, assignee, appCode);
                    if(tasks != null && tasks.size() > 0) {
                        task = tasks.get(0);
                        taskName = task.getName();
                        dataList = dataAuditRepository.findByFlowInstanceId(flowId);
                        this.saveTDataAuditDetails(dataList, taskName, comment, assignee);
                        tasksService.finishTask(task, comment, null, null);
                        this.saveDataAuditRecord(data,  taskName, assignee, comment);
                    }
                }
            }
        }
        if(taskName.equals("")) {
            return new ResultEntity(ResultStatus.ERROR,"审核无权限");
        }
        return new ResultEntity(ResultStatus.SUCCESS,"审核完成");
    }

   

    @Override
    public ResultEntity auditCustomer(DataAuditVO vo, String appCode) {
        if(vo == null) {
            return new ResultEntity(ResultStatus.ERROR, Constants.PARAM_ERROR);
        }
        List<DataAuditBO> list = vo.getList();
        String assignee = vo.getUserId();
        String comment = vo.getComment();
        String userId = vo.getUserId();
        System.out.println("登陆用户id=== "+userId);
        TDataAudit data = null;
        List<TDataAuditSignRecord> signList = new ArrayList<>();
        TDataAuditSignRecord signRecord = null;
        String taskName = "";
        Task task = null;
        List<Task> tasks = null;
        List<TDataAuditDetail> details = new ArrayList<>();
        TDataAuditDetail detail = null;
        for (DataAuditBO bo: list) {
            String id = bo.getId();
            if(id != null) {
                data = dataAuditRepository.findById(id).get();
                signRecord = new TDataAuditSignRecord();
                signRecord.setAuditUser(assignee);
                signRecord.setProjName(data.getProjName());
                signRecord.setAuditReason(bo.getRemark());
                signRecord.setAuditOperation(comment);
                signList.add(signRecord);
                this.setSignRecord(data, signRecord);
                String flowId = data.getFlowInstanceId();
                tasks = tasksService.queryTask(flowId, assignee, appCode);
                task = null;
                if(tasks != null && tasks.size() > 0) {
                    task = tasks.get(0);
                }
                if(task != null) {
                    taskName = task.getName();
                    System.out.println("task name === "+taskName);
                }else {
                    taskName = "";
                }
                detail = this.setDataAuditDatail(data, bo, taskName, comment, assignee);
                if(detail != null)
                    details.add(detail);
            }
        }
        
        dataAuditSignRecordRepository.saveAll(signList);
        dataAuditDetailRepository.saveAll(details); 
        return new ResultEntity(ResultStatus.SUCCESS, Constants.UPDATE_SUCCESS);
    }
    
    /**
     * 数据审核详情
     *  存储更新
     * @author 蔡永顺
     * @return TDataAuditDetail
     * @param data
     * @param bo
     * @param taskName
     * @param comment
     * @param assignee
     * @return
     * @date 2019年5月9日上午10:51:54
     */
    private TDataAuditDetail setDataAuditDatail(TDataAudit data, DataAuditBO bo, String taskName,
            String comment, String assignee) {
        if(data == null || taskName.equals("")) {
            return null;
        }
        List<TDataAuditDetail> details = data.getAuditDetailsList();
        TDataAuditDetail  detail = null;
        for (TDataAuditDetail tDataAuditDetail : details) {
            if(taskName.equals(tDataAuditDetail.getTaskName())) {
                detail =  tDataAuditDetail;
                break;
            }
        }
        if(detail == null) {
            detail = new TDataAuditDetail();
            detail.setTaskName(taskName);
            detail.setDataAudit(data);
        }
        detail.setAuditConDesc(comment);
        detail.setAuditUser(assignee);
        detail.setAuditStatus(bo.getColorStatus()+"");
        detail.setAuditDesc(bo.getRemark());
        return detail;
    }

    private void setSignRecord(TDataAudit data, TDataAuditSignRecord signRecord) {
        signRecord.setAuditDate(new Date());
        signRecord.setFlowInstanceId(data.getFlowInstanceId());
        signRecord.setProjId(data.getProjId());
        signRecord.setProjName(data.getProjName());
        signRecord.setProjValue(data.getProjValue());
        signRecord.setStationDate(data.getCreateTime());
        signRecord.setStationMn(data.getStationMn());
    }

    private void saveDataAuditRecord(TDataAudit data,  String taskName, String assignee,
            String comment) {
        TDataAuditRecord record = new TDataAuditRecord();
        record.setAuditDate(new Date());
        if (taskName.equals(Constants.ONE_AUDIT_CLASS)) {
            record.setAuditOperation(Constants.ONE_AUDIT_OPERATION);
        } else if (taskName.equals(Constants.TWO_AUDIT_CLASS)) {
            record.setAuditOperation(Constants.TWO_AUDIT_OPERATION);
        } else if (taskName.equals(Constants.THREE_AUDIT_CLASS)) {
            record.setAuditOperation(Constants.THREE_AUDIT_OPERATION);
        } else {
        }
        record.setAuditReason(comment);
        record.setAuditUser(assignee);
        record.setFlowInstanceId(data.getFlowInstanceId());
        record.setStationDate(data.getCreateTime());
        record.setStationMn(data.getStationMn());
        dataAuditRecordRepository.save(record);
        
    }

    @Override
    public ResultEntity saveEvidenceFile(MultipartFile file, String userId, String dataId) {
        if (file == null) {
            return new ResultEntity(ResultStatus.ERROR, Constants.PARAM_ERROR);
        }
        try {
            String fileName = file.getOriginalFilename();
            int pointIndex = fileName.lastIndexOf(".");// 点号的位置
            String fileSuffix = fileName.substring(pointIndex);// 截取文件后缀
            // String fileNewName = DateUtils..getNowTimeForUpload();//文件new名称时间戳
            TEvidenceFile evidenceFile = new TEvidenceFile();
            String uid = UUIDGenerator.randomUUID();
            String saveFileName = uid.concat(fileSuffix);// 文件存取名
            evidenceFile.setFileName(fileName);
            evidenceFile.setCreateTime(new Date());
            evidenceFile.setFileSize(file.getSize());
            String path = File.separator + uid;
            File floder = new File(Constants.BASE_PATH + path);
            if (!floder.exists()) {
                floder.mkdirs();
            }
            String filePath = path +File.separator + saveFileName;
            evidenceFile.setFilePath(filePath);
            evidenceFile.setCreateName(userId);
            evidenceFile.setAuditDataId(dataId);
            evidenceRepository.saveAndFlush(evidenceFile);
            File saveFile = new File(Constants.BASE_PATH + filePath);
            if(saveFile.createNewFile())
                file.transferTo(saveFile);
        } catch (IllegalStateException e) {
            return new ResultEntity(ResultStatus.ERROR, e.getMessage());
        } catch (IOException e) {
            return new ResultEntity(ResultStatus.ERROR, e.getMessage());
        }
        return new ResultEntity(ResultStatus.SUCCESS, Constants.UPLOAD_SUCCESS);
    }
    
    @Override
    public ResultEntity statisDataAudit(AuditRecordQuery query) {
        List<String> stationMnList = query.getStationMnList();
        String time = query.getStartTime();
        List<String> timeDayList = DateFormatUtil.getMonthDayList(time);
        Map<String,Object> re = new HashMap<>();
        re.put("head", AuditDataCovertUtil.getDataAuditMonthHead(timeDayList));
        List<Map<String, DataAuditBO>> body = new ArrayList<>();
        re.put("body", body);
        List<Map<String,Object>> list = dataAuditRepository.queryDataAuditGroupByMnsTime
                    (stationMnList, timeDayList.get(0), timeDayList.get(timeDayList.size()-1));
        HistoricProcessInstance hisInstance = null;
        List<String> flowIds = new ArrayList<>();
        Set<String> stationMns = new HashSet<>();
        Map<String, StationInfo> stationInfoMap = this.queryStationInfos(stationMnList);
        Map<String, DataAuditBO> boMap = null;
        DataAuditBO bo = null;
        Map<String, Map<String, DataAuditBO>> bodyKeyMap = new HashMap<>();
        for (String stationMn : stationMnList) {
            boMap = new HashMap<>();
            this.setDataAuditBOBody(boMap, timeDayList);
            body.add(boMap);
            bodyKeyMap.put(stationMn, boMap);
            String stationName = null;
            String stationComp = null;
            if(stationInfoMap.get(stationMn) != null) {
                stationName = stationInfoMap.get(stationMn).getStationName();
                stationComp = stationInfoMap.get(stationMn).getStationCompany();
            }
            //站点
            bo = new DataAuditBO();
            bo.setName(stationMn);
            bo.setValue(stationName);
            boMap.put("station", bo);
            //站点Mn
            bo = new DataAuditBO();
            bo.setName(stationMn);
            bo.setValue(stationMn);
            boMap.put("stationMn", bo);
            //站点运维单位
            bo = new DataAuditBO();
            bo.setName(stationMn);
            bo.setValue(stationComp);
            boMap.put("stationCom", bo);
        }
        for (Map<String, Object> map : list) {
            String flowId = map.get("FLOWID").toString();
            String stationMn = map.get("STATION_MN").toString();
            String day = map.get("CTIME").toString();
            stationMns.add(stationMn);
            hisInstance = historyService.createHistoricProcessInstanceQuery().
                    processInstanceId(flowId).finished().singleResult();
            boMap = bodyKeyMap.get(stationMn);
            if(hisInstance != null && boMap != null) {
                flowIds.add(flowId);
                boMap.get(day).setValue(this.setAuditStatusByFlow(flowId));
            //    System.out.println("已审核--- "+time);
             //   mapVo.get(time).setStatus(Constants.AUDITED_STATUS);
            }else {
             //   mapVo.get(time).setStatus(Constants.AUDITING_STATUS);
            }
            
        }
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(re);
    }
    
    /**
     * 无效于存疑取舍
     * 无效权重最高 
     * 
     * @author 蔡永顺
     * @return String
     * @param flowId
     * @return
     * @date 2019年5月14日上午9:28:18
     */
    private String setAuditStatusByFlow(String flowId) {
        List<TDataAuditDetail> list = dataAuditDetailRepository.findByTaskNameAndDataAuditFlowInstanceIdAndAuditStatusNot
                    (Constants.THREE_AUDIT_CLASS, flowId, AuditStatus.VALIDE.getStatusCode());
        String invalide = null;
        String doubt = null;
        if(list != null && list.size() > 0) {
            for (TDataAuditDetail detail : list) {
                if( detail.getAuditStatus().equals(AuditStatus.INVALIDE.getStatusCode())) {
                    invalide = detail.getAuditStatus();
                    break;
                }else if( detail.getAuditStatus().equals(AuditStatus.DOUBT.getStatusCode())){
                    doubt = detail.getAuditStatus();
                }
            }
        }
        if(invalide != null) {
            return invalide;
        }
        if(doubt != null) {
            return doubt;
        }
        return AuditStatus.VALIDE.getStatusCode();
    }

    private void setDataAuditBOBody(Map<String, DataAuditBO> boMap, List<String> timeDayList) {
        DataAuditBO bo = null;
        for (String day : timeDayList) {
            bo = new DataAuditBO();
            bo.setName(day);
            boMap.put(day, bo);
        }
        
    }

    @Override
    public ResultEntity statisDataAudit(List<StatisAuditDateVO> listVo) {
       // String mn, String startTime, String endTime
        if(listVo == null || listVo.size() < 4) {
            return new ResultEntity(ResultStatus.ERROR, Constants.PARAM_ERROR);
        }
        Map<String,StatisAuditDateVO> mapVo = new HashMap<>();
        String mn = null;
        for (StatisAuditDateVO vo : listVo) {
            mn = vo.getMn();
            vo.setStatus(Constants.AUDITING_STATUS);
            mapVo.put(vo.getDatetime(), vo);
        }
        String startTime =  listVo.get(0).getDatetime();
        String endTime = listVo.get(listVo.size() - 1).getDatetime();
        List<Map<String,Object>> list = dataAuditRepository.queryDataAuditGroupByTime(mn, startTime, endTime);
        HistoricProcessInstance hisInstance = null;
        for (Map<String, Object> map : list) {
            String flowId = map.get("FLOWID").toString();
            String time = map.get("CTIME").toString();
            hisInstance = historyService.createHistoricProcessInstanceQuery().
                    processInstanceId(flowId).finished().singleResult();
            if(hisInstance != null) {
            //    System.out.println("已审核--- "+time);
                mapVo.get(time).setStatus(Constants.AUDITED_STATUS);
            }else {
                mapVo.get(time).setStatus(Constants.AUDITING_STATUS);
            }
            
        }
        
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(listVo);
    }

    @Override
    public ResultEntity queryAuditOperaRecordByFlow(String flowId) {
        if(flowId == null) {
            return new ResultEntity(ResultStatus.ERROR, Constants.PARAM_ERROR);
        }
        List<Map<String,Object>> list = dataAuditRecordRepository.queryAuditOperaRecordByFlow(flowId);
        List<Map<String,Object>> newList  = new ArrayList<>();
        Map<String,Object> newMap = null;
        for (Map<String, Object> map : list) {
            newMap = new HashMap<>();
            newMap.putAll(map);
            newList.add(newMap);
            String userId = map.get("AUDIT_USER").toString();
            if(StringUtils.isNotBlank(userId)) {
                String name = AirAuditUsers.getReasonByCode(userId);
                if(StringUtils.isNotBlank(name)) {
                    newMap.put("AUDIT_USER", name);
                }else {
                    newMap.put("AUDIT_USER", "assignee");
                }
            }
        }
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(newList);
    }

    @Override
    public ResultEntity rejectDataAudit(String mn, String date, String userId, Integer reviewPass,String comment) {
        String flowId = this.queryFlowIdByMnAndDate(mn, date);
        if(flowId == null) {
            return new ResultEntity(ResultStatus.ERROR, "未有此流程实例");  
        }
        List<Task> tasks = tasksService.queryTask(flowId, userId,"");
        Task task = null;
        if(tasks != null  && tasks.size() > 0) {
            task = tasks.get(0);
        }
    //    System.out.println(task.getName());
        if(task != null  && task.getName().equals(Constants.THREE_AUDIT_CLASS)) {
            tasksService.finishTask(task, comment, null, reviewPass);
            return new ResultEntity(ResultStatus.SUCCESS, "驳回成功");
        }
        return new ResultEntity(ResultStatus.ERROR, "无权限驳回或已审批结束!");
    }

    private String queryFlowIdByMnAndDate(String mn, String date) {
        Map<String,Object> map = dataAuditRepository.queryFlowIdByMnAndDate(mn, date);
        String flowId = null;
        if(map != null) {
            flowId = map.get("FLOW_INSTANCE_ID") == null ? null :map.get("FLOW_INSTANCE_ID").toString();
        }
        return flowId;
    }

    @Override
    public ResultEntity queryEvidenceFile(String flowId) {
        List<TEvidenceFile> list = evidenceRepository.findByAuditDataId(flowId);
        return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(list);
    }

    
    
}
